package auth_svc

import (
	"admin-system/internal/dao"
	"admin-system/internal/models/auth_model"
	"admin-system/internal/request"
	"errors"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"log/slog"
)

type MenuService struct {
	dao *dao.DaoProvider
}

func NewMenuService(dao *dao.DaoProvider) *MenuService {
	return &MenuService{
		dao: dao,
	}
}

// GetMenuIdsByRole
// 查询当前角色下的菜单
// @Summary 获取菜单集合
func (m *MenuService) GetMenuIdsByRole(c *gin.Context, roleId int64) ([]int64, error) {
	// 获取 角色下的菜单列表(从 role_menu表中获取)
	roleMenu, err := m.dao.RoleMenuDao.GetMenuListByRoleId(c, roleId)
	if err != nil {
		slog.Error("获取菜单集合失败", "err", err)
		return nil, err
	}
	menuIds := make([]int64, 0)
	// 提取menu_id 到定义的切片
	for _, v := range roleMenu {
		menuIds = append(menuIds, v.MenuID)
	}
	return menuIds, nil
}

// GetMenuList
//
//	@Summary 获取菜单列表
func (m *MenuService) GetMenuList(c *gin.Context, ids []int64) (menu []auth_model.Menu, err error) {
	// 后台渲染菜单列表时获取所有状态的菜单
	// FIXME: 可变参数，传空值默认查所有的菜单、传1 查启用的菜单（未被隐藏状态为：0，前端获取，菜单路由时需要传值）
	var status *int64
	// 查询菜单列表
	if menu, err = m.dao.MenuDao.GetMenuList(c, ids, status); err != nil {
		return nil, err
	}
	// 构建菜单树结构
	treeMenu := buildMenuTree(menu, 0)
	return treeMenu, nil
}

func buildMenuTree(menuList []auth_model.Menu, parentID int64) []auth_model.Menu {
	var tree []auth_model.Menu
	for _, menu := range menuList {
		if menu.ParentID == parentID {
			children := buildMenuTree(menuList, menu.ID)
			menu.Children = children
			tree = append(tree, menu)
		}
	}
	return tree
}

//	CreateMenu
//
// @Summary 创建菜单
func (m *MenuService) SaveMenu(c *gin.Context, req request.MenuRequest) (*auth_model.Menu, error) {
	// 创建菜单
	menu := &auth_model.Menu{
		ID:        req.ID,
		ParentID:  req.ParentID,
		Component: req.Component,
		Hidden:    req.Hidden,
		Icon:      req.Icon,
		KeepAlive: req.KeepAlive,
		Name:      req.Name,
		OrderNum:  req.OrderNum,
		Path:      req.Path,
		Redirect:  req.Redirect,
	}
	if err := m.dao.MenuDao.SaveMenu(c, menu); err != nil {
		if req.ID == 0 {
			return nil, errors.New("菜单新增失败！")
		} else {
			return nil, errors.New("菜单修改失败！")
		}
	}
	return menu, nil
}

// GetMenuByID 根据ID获取菜单详情
//
//	@description service层获取菜单详情
//	@Summary 获取菜单详情
func (m *MenuService) GetMenuByID(c *gin.Context, menuId int64) (menu *auth_model.Menu, err error) {
	if menu, err = m.dao.MenuDao.GetMenuByID(c, menuId); err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("菜单不存在")
		}
	}
	return menu, nil
}

// DeleteMenu 删除菜单
// @param menuId int64
func (m *MenuService) DeleteMenu(c *gin.Context, menuId int64) error {
	if err := m.dao.MenuDao.DelMenu(c, menuId); err != nil {
		return errors.New("菜单删除失败")
	}
	return nil
}
